import functools
import json
import pytest

from eth_utils import (
    event_signature_to_log_topic,
)

from web3._utils.module_testing.emitter_contract import (
    CONTRACT_EMITTER_ABI,
    CONTRACT_EMITTER_CODE,
    CONTRACT_EMITTER_RUNTIME,
)
from web3._utils.module_testing.event_contract import (
    EVNT_CONTRACT_ABI,
    EVNT_CONTRACT_CODE,
    EVNT_CONTRACT_RUNTIME,
)
from web3._utils.module_testing.fallback_contract import (
    CONTRACT_FALLBACK_FUNCTION_ABI,
    CONTRACT_FALLBACK_FUNCTION_CODE,
    CONTRACT_FALLBACK_FUNCTION_RUNTIME,
)
from web3._utils.module_testing.indexed_event_contract import (
    IND_EVENT_CONTRACT_ABI,
    IND_EVENT_CONTRACT_CODE,
    IND_EVENT_CONTRACT_RUNTIME,
)
from web3._utils.module_testing.no_receive_contract import (
    CONTRACT_NO_RECEIVE_FUNCTION_ABI,
    CONTRACT_NO_RECEIVE_FUNCTION_CODE,
    CONTRACT_NO_RECEIVE_FUNCTION_RUNTIME,
)
from web3._utils.module_testing.receive_contract import (
    CONTRACT_RECEIVE_FUNCTION_ABI,
    CONTRACT_RECEIVE_FUNCTION_CODE,
    CONTRACT_RECEIVE_FUNCTION_RUNTIME,
)

CONTRACT_NESTED_TUPLE_SOURCE = """
pragma solidity >=0.4.19 <0.6.0;
pragma experimental ABIEncoderV2;

contract Tuple {
    struct U { int x; int y; }
    struct T { U[] u; }
    struct S { T[] t; }

    function method(S memory s) public pure returns (S memory) {
        return s;
    }
}
"""
CONTRACT_NESTED_TUPLE_CODE = '0x608060405234801561001057600080fd5b50610575806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632655aef114610046575b600080fd5b34801561005257600080fd5b5061006d600480360361006891908101906102a2565b610083565b60405161007a919061043e565b60405180910390f35b61008b610093565b819050919050565b602060405190810160405280606081525090565b600082601f83011215156100ba57600080fd5b81356100cd6100c88261048d565b610460565b9150818183526020840193506020810190508360005b8381101561011357813586016100f98882610206565b8452602084019350602083019250506001810190506100e3565b5050505092915050565b600082601f830112151561013057600080fd5b813561014361013e826104b5565b610460565b9150818183526020840193506020810190508385604084028201111561016857600080fd5b60005b83811015610198578161017e8882610256565b84526020840193506040830192505060018101905061016b565b5050505092915050565b60006101ae8235610531565b905092915050565b6000602082840312156101c857600080fd5b6101d26020610460565b9050600082013567ffffffffffffffff8111156101ee57600080fd5b6101fa848285016100a7565b60008301525092915050565b60006020828403121561021857600080fd5b6102226020610460565b9050600082013567ffffffffffffffff81111561023e57600080fd5b61024a8482850161011d565b60008301525092915050565b60006040828403121561026857600080fd5b6102726040610460565b90506000610282848285016101a2565b6000830152506020610296848285016101a2565b60208301525092915050565b6000602082840312156102b457600080fd5b600082013567ffffffffffffffff8111156102ce57600080fd5b6102da848285016101b6565b91505092915050565b60006102ee826104f7565b80845260208401935083602082028501610307856104dd565b60005b848110156103405783830388526103228383516103e5565b925061032d8261050d565b915060208801975060018101905061030a565b508196508694505050505092915050565b600061035c82610502565b80845260208401935061036e836104ea565b60005b828110156103a05761038486835161040f565b61038d8261051a565b9150604086019550600181019050610371565b50849250505092915050565b6103b581610527565b82525050565b600060208301600083015184820360008601526103d882826102e3565b9150508091505092915050565b600060208301600083015184820360008601526104028282610351565b9150508091505092915050565b60408201600082015161042560008501826103ac565b50602082015161043860208501826103ac565b50505050565b6000602082019050818103600083015261045881846103bb565b905092915050565b6000604051905081810181811067ffffffffffffffff8211171561048357600080fd5b8060405250919050565b600067ffffffffffffffff8211156104a457600080fd5b602082029050602081019050919050565b600067ffffffffffffffff8211156104cc57600080fd5b602082029050602081019050919050565b6000602082019050919050565b6000602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000819050919050565b60008190509190505600a265627a7a7230582011dc176b6cffda1d2e58827bca1a16178776c2d8efcd6adf48bc0223f14f891a6c6578706572696d656e74616cf50037'  # noqa: E501
CONTRACT_NESTED_TUPLE_RUNTIME = '0x608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680632655aef114610046575b600080fd5b34801561005257600080fd5b5061006d600480360361006891908101906102a2565b610083565b60405161007a919061043e565b60405180910390f35b61008b610093565b819050919050565b602060405190810160405280606081525090565b600082601f83011215156100ba57600080fd5b81356100cd6100c88261048d565b610460565b9150818183526020840193506020810190508360005b8381101561011357813586016100f98882610206565b8452602084019350602083019250506001810190506100e3565b5050505092915050565b600082601f830112151561013057600080fd5b813561014361013e826104b5565b610460565b9150818183526020840193506020810190508385604084028201111561016857600080fd5b60005b83811015610198578161017e8882610256565b84526020840193506040830192505060018101905061016b565b5050505092915050565b60006101ae8235610531565b905092915050565b6000602082840312156101c857600080fd5b6101d26020610460565b9050600082013567ffffffffffffffff8111156101ee57600080fd5b6101fa848285016100a7565b60008301525092915050565b60006020828403121561021857600080fd5b6102226020610460565b9050600082013567ffffffffffffffff81111561023e57600080fd5b61024a8482850161011d565b60008301525092915050565b60006040828403121561026857600080fd5b6102726040610460565b90506000610282848285016101a2565b6000830152506020610296848285016101a2565b60208301525092915050565b6000602082840312156102b457600080fd5b600082013567ffffffffffffffff8111156102ce57600080fd5b6102da848285016101b6565b91505092915050565b60006102ee826104f7565b80845260208401935083602082028501610307856104dd565b60005b848110156103405783830388526103228383516103e5565b925061032d8261050d565b915060208801975060018101905061030a565b508196508694505050505092915050565b600061035c82610502565b80845260208401935061036e836104ea565b60005b828110156103a05761038486835161040f565b61038d8261051a565b9150604086019550600181019050610371565b50849250505092915050565b6103b581610527565b82525050565b600060208301600083015184820360008601526103d882826102e3565b9150508091505092915050565b600060208301600083015184820360008601526104028282610351565b9150508091505092915050565b60408201600082015161042560008501826103ac565b50602082015161043860208501826103ac565b50505050565b6000602082019050818103600083015261045881846103bb565b905092915050565b6000604051905081810181811067ffffffffffffffff8211171561048357600080fd5b8060405250919050565b600067ffffffffffffffff8211156104a457600080fd5b602082029050602081019050919050565b600067ffffffffffffffff8211156104cc57600080fd5b602082029050602081019050919050565b6000602082019050919050565b6000602082019050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000819050919050565b60008190509190505600a265627a7a7230582011dc176b6cffda1d2e58827bca1a16178776c2d8efcd6adf48bc0223f14f891a6c6578706572696d656e74616cf50037'  # noqa: E501
CONTRACT_NESTED_TUPLE_ABI = json.loads('[{"constant":true,"inputs":[{"components":[{"components":[{"components":[{"name":"x","type":"int256"},{"name":"y","type":"int256"}],"name":"u","type":"tuple[]"}],"name":"t","type":"tuple[]"}],"name":"s","type":"tuple"}],"name":"method","outputs":[{"components":[{"components":[{"components":[{"name":"x","type":"int256"},{"name":"y","type":"int256"}],"name":"u","type":"tuple[]"}],"name":"t","type":"tuple[]"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"}]')  # noqa: E501


@pytest.fixture()
def NESTED_TUPLE_CODE():
    return CONTRACT_NESTED_TUPLE_CODE


@pytest.fixture()
def NESTED_TUPLE_RUNTIME():
    return CONTRACT_NESTED_TUPLE_RUNTIME


@pytest.fixture()
def NESTED_TUPLE_ABI():
    return CONTRACT_NESTED_TUPLE_ABI


@pytest.fixture()
def NESTED_TUPLE_CONTRACT(NESTED_TUPLE_CODE, NESTED_TUPLE_RUNTIME, NESTED_TUPLE_ABI):
    return {
        'bytecode': NESTED_TUPLE_CODE,
        'bytecode_runtime': NESTED_TUPLE_RUNTIME,
        'abi': NESTED_TUPLE_ABI,
    }


@pytest.fixture()
def NestedTupleContract(web3, NESTED_TUPLE_CONTRACT):
    return web3.eth.contract(**NESTED_TUPLE_CONTRACT)


CONTRACT_TUPLE_SOURCE = """
pragma solidity >=0.4.19 <0.6.0;
pragma experimental ABIEncoderV2;

contract Tuple {
    struct T { int x; bool[2] y; address[] z; }
    struct S { uint a; uint[] b; T[] c; }

    function method(S memory s) public pure returns (S memory) {
        return s;
    }
}
"""
CONTRACT_TUPLE_CODE = '0x608060405234801561001057600080fd5b506108ca806100206000396000f300608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680638e1ae3c714610046575b600080fd5b34801561005257600080fd5b5061006d60048036036100689190810190610403565b610083565b60405161007a9190610696565b60405180910390f35b61008b610093565b819050919050565b6060604051908101604052806000815260200160608152602001606081525090565b60006100c18235610850565b905092915050565b600082601f83011215156100dc57600080fd5b81356100ef6100ea826106e5565b6106b8565b9150818183526020840193506020810190508385602084028201111561011457600080fd5b60005b83811015610144578161012a88826100b5565b845260208401935060208301925050600181019050610117565b5050505092915050565b600082601f830112151561016157600080fd5b600261017461016f8261070d565b6106b8565b9150818385602084028201111561018a57600080fd5b60005b838110156101ba57816101a088826102bf565b84526020840193506020830192505060018101905061018d565b5050505092915050565b600082601f83011215156101d757600080fd5b81356101ea6101e58261072f565b6106b8565b9150818183526020840193506020810190508360005b8381101561023057813586016102168882610377565b845260208401935060208301925050600181019050610200565b5050505092915050565b600082601f830112151561024d57600080fd5b813561026061025b82610757565b6106b8565b9150818183526020840193506020810190508385602084028201111561028557600080fd5b60005b838110156102b5578161029b88826103ef565b845260208401935060208301925050600181019050610288565b5050505092915050565b60006102cb8235610870565b905092915050565b60006102df823561087c565b905092915050565b6000606082840312156102f957600080fd5b61030360606106b8565b90506000610313848285016103ef565b600083015250602082013567ffffffffffffffff81111561033357600080fd5b61033f8482850161023a565b602083015250604082013567ffffffffffffffff81111561035f57600080fd5b61036b848285016101c4565b60408301525092915050565b60006080828403121561038957600080fd5b61039360606106b8565b905060006103a3848285016102d3565b60008301525060206103b78482850161014e565b602083015250606082013567ffffffffffffffff8111156103d757600080fd5b6103e3848285016100c9565b60408301525092915050565b60006103fb8235610886565b905092915050565b60006020828403121561041557600080fd5b600082013567ffffffffffffffff81111561042f57600080fd5b61043b848285016102e7565b91505092915050565b61044d81610810565b82525050565b600061045e826107b0565b8084526020840193506104708361077f565b60005b828110156104a257610486868351610444565b61048f826107dc565b9150602086019550600181019050610473565b50849250505092915050565b6104b7816107bb565b6104c08261078c565b60005b828110156104f2576104d68583516105c2565b6104df826107e9565b91506020850194506001810190506104c3565b5050505050565b6000610504826107c6565b8084526020840193508360208202850161051d85610796565b60005b84811015610556578383038852610538838351610637565b9250610543826107f6565b9150602088019750600181019050610520565b508196508694505050505092915050565b6000610572826107d1565b808452602084019350610584836107a3565b60005b828110156105b65761059a868351610687565b6105a382610803565b9150602086019550600181019050610587565b50849250505092915050565b6105cb81610830565b82525050565b6105da8161083c565b82525050565b60006060830160008301516105f86000860182610687565b50602083015184820360208601526106108282610567565b9150506040830151848203604086015261062a82826104f9565b9150508091505092915050565b600060808301600083015161064f60008601826105d1565b50602083015161066260208601826104ae565b506040830151848203606086015261067a8282610453565b9150508091505092915050565b61069081610846565b82525050565b600060208201905081810360008301526106b081846105e0565b905092915050565b6000604051905081810181811067ffffffffffffffff821117156106db57600080fd5b8060405250919050565b600067ffffffffffffffff8211156106fc57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561072457600080fd5b602082029050919050565b600067ffffffffffffffff82111561074657600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561076e57600080fd5b602082029050602081019050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b6000602082019050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b60008190509190505600a265627a7a72305820fb4abae14c4bcd2cd8a12f35862cb09a2e0f9004eb5fdbfdb76658a753570c8c6c6578706572696d656e74616cf50037'  # noqa: E501
CONTRACT_TUPLE_RUNTIME = '0x608060405260043610610041576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680638e1ae3c714610046575b600080fd5b34801561005257600080fd5b5061006d60048036036100689190810190610403565b610083565b60405161007a9190610696565b60405180910390f35b61008b610093565b819050919050565b6060604051908101604052806000815260200160608152602001606081525090565b60006100c18235610850565b905092915050565b600082601f83011215156100dc57600080fd5b81356100ef6100ea826106e5565b6106b8565b9150818183526020840193506020810190508385602084028201111561011457600080fd5b60005b83811015610144578161012a88826100b5565b845260208401935060208301925050600181019050610117565b5050505092915050565b600082601f830112151561016157600080fd5b600261017461016f8261070d565b6106b8565b9150818385602084028201111561018a57600080fd5b60005b838110156101ba57816101a088826102bf565b84526020840193506020830192505060018101905061018d565b5050505092915050565b600082601f83011215156101d757600080fd5b81356101ea6101e58261072f565b6106b8565b9150818183526020840193506020810190508360005b8381101561023057813586016102168882610377565b845260208401935060208301925050600181019050610200565b5050505092915050565b600082601f830112151561024d57600080fd5b813561026061025b82610757565b6106b8565b9150818183526020840193506020810190508385602084028201111561028557600080fd5b60005b838110156102b5578161029b88826103ef565b845260208401935060208301925050600181019050610288565b5050505092915050565b60006102cb8235610870565b905092915050565b60006102df823561087c565b905092915050565b6000606082840312156102f957600080fd5b61030360606106b8565b90506000610313848285016103ef565b600083015250602082013567ffffffffffffffff81111561033357600080fd5b61033f8482850161023a565b602083015250604082013567ffffffffffffffff81111561035f57600080fd5b61036b848285016101c4565b60408301525092915050565b60006080828403121561038957600080fd5b61039360606106b8565b905060006103a3848285016102d3565b60008301525060206103b78482850161014e565b602083015250606082013567ffffffffffffffff8111156103d757600080fd5b6103e3848285016100c9565b60408301525092915050565b60006103fb8235610886565b905092915050565b60006020828403121561041557600080fd5b600082013567ffffffffffffffff81111561042f57600080fd5b61043b848285016102e7565b91505092915050565b61044d81610810565b82525050565b600061045e826107b0565b8084526020840193506104708361077f565b60005b828110156104a257610486868351610444565b61048f826107dc565b9150602086019550600181019050610473565b50849250505092915050565b6104b7816107bb565b6104c08261078c565b60005b828110156104f2576104d68583516105c2565b6104df826107e9565b91506020850194506001810190506104c3565b5050505050565b6000610504826107c6565b8084526020840193508360208202850161051d85610796565b60005b84811015610556578383038852610538838351610637565b9250610543826107f6565b9150602088019750600181019050610520565b508196508694505050505092915050565b6000610572826107d1565b808452602084019350610584836107a3565b60005b828110156105b65761059a868351610687565b6105a382610803565b9150602086019550600181019050610587565b50849250505092915050565b6105cb81610830565b82525050565b6105da8161083c565b82525050565b60006060830160008301516105f86000860182610687565b50602083015184820360208601526106108282610567565b9150506040830151848203604086015261062a82826104f9565b9150508091505092915050565b600060808301600083015161064f60008601826105d1565b50602083015161066260208601826104ae565b506040830151848203606086015261067a8282610453565b9150508091505092915050565b61069081610846565b82525050565b600060208201905081810360008301526106b081846105e0565b905092915050565b6000604051905081810181811067ffffffffffffffff821117156106db57600080fd5b8060405250919050565b600067ffffffffffffffff8211156106fc57600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561072457600080fd5b602082029050919050565b600067ffffffffffffffff82111561074657600080fd5b602082029050602081019050919050565b600067ffffffffffffffff82111561076e57600080fd5b602082029050602081019050919050565b6000602082019050919050565b6000819050919050565b6000602082019050919050565b6000602082019050919050565b600081519050919050565b600060029050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b6000819050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60008115159050919050565b6000819050919050565b60008190509190505600a265627a7a72305820fb4abae14c4bcd2cd8a12f35862cb09a2e0f9004eb5fdbfdb76658a753570c8c6c6578706572696d656e74616cf50037'  # noqa: E501
CONTRACT_TUPLE_ABI = json.loads('[{"constant":true,"inputs":[{"components":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256[]"},{"components":[{"name":"x","type":"int256"},{"name":"y","type":"bool[2]"},{"name":"z","type":"address[]"}],"name":"c","type":"tuple[]"}],"name":"s","type":"tuple"}],"name":"method","outputs":[{"components":[{"name":"a","type":"uint256"},{"name":"b","type":"uint256[]"},{"components":[{"name":"x","type":"int256"},{"name":"y","type":"bool[2]"},{"name":"z","type":"address[]"}],"name":"c","type":"tuple[]"}],"name":"","type":"tuple"}],"payable":false,"stateMutability":"pure","type":"function"}]')  # noqa: E501


@pytest.fixture()
def TUPLE_CODE():
    return CONTRACT_TUPLE_CODE


@pytest.fixture()
def TUPLE_RUNTIME():
    return CONTRACT_TUPLE_RUNTIME


@pytest.fixture()
def TUPLE_ABI():
    return CONTRACT_TUPLE_ABI


@pytest.fixture()
def TUPLE_CONTRACT(TUPLE_CODE, TUPLE_RUNTIME, TUPLE_ABI):
    return {
        'bytecode': TUPLE_CODE,
        'bytecode_runtime': TUPLE_RUNTIME,
        'abi': TUPLE_ABI,
    }


@pytest.fixture()
def TupleContract(web3, TUPLE_CONTRACT):
    return web3.eth.contract(**TUPLE_CONTRACT)


CONTRACT_CODE = "0x606060405261022e806100126000396000f360606040523615610074576000357c01000000000000000000000000000000000000000000000000000000009004806316216f391461007657806361bc221a146100995780637cf5dab0146100bc578063a5f3c23b146100e8578063d09de08a1461011d578063dcf537b11461014057610074565b005b610083600480505061016c565b6040518082815260200191505060405180910390f35b6100a6600480505061017f565b6040518082815260200191505060405180910390f35b6100d26004808035906020019091905050610188565b6040518082815260200191505060405180910390f35b61010760048080359060200190919080359060200190919050506101ea565b6040518082815260200191505060405180910390f35b61012a6004805050610201565b6040518082815260200191505060405180910390f35b6101566004808035906020019091905050610217565b6040518082815260200191505060405180910390f35b6000600d9050805080905061017c565b90565b60006000505481565b6000816000600082828250540192505081905550600060005054905080507f3496c3ede4ec3ab3686712aa1c238593ea6a42df83f98a5ec7df9834cfa577c5816040518082815260200191505060405180910390a18090506101e5565b919050565b6000818301905080508090506101fb565b92915050565b600061020d6001610188565b9050610214565b90565b60006007820290508050809050610229565b91905056"  # noqa: E501


CONTRACT_RUNTIME = "0x60606040523615610074576000357c01000000000000000000000000000000000000000000000000000000009004806316216f391461007657806361bc221a146100995780637cf5dab0146100bc578063a5f3c23b146100e8578063d09de08a1461011d578063dcf537b11461014057610074565b005b610083600480505061016c565b6040518082815260200191505060405180910390f35b6100a6600480505061017f565b6040518082815260200191505060405180910390f35b6100d26004808035906020019091905050610188565b6040518082815260200191505060405180910390f35b61010760048080359060200190919080359060200190919050506101ea565b6040518082815260200191505060405180910390f35b61012a6004805050610201565b6040518082815260200191505060405180910390f35b6101566004808035906020019091905050610217565b6040518082815260200191505060405180910390f35b6000600d9050805080905061017c565b90565b60006000505481565b6000816000600082828250540192505081905550600060005054905080507f3496c3ede4ec3ab3686712aa1c238593ea6a42df83f98a5ec7df9834cfa577c5816040518082815260200191505060405180910390a18090506101e5565b919050565b6000818301905080508090506101fb565b92915050565b600061020d6001610188565b9050610214565b90565b60006007820290508050809050610229565b91905056"  # noqa: E501


CONTRACT_ABI = json.loads('[{"constant":false,"inputs":[],"name":"return13","outputs":[{"name":"result","type":"int256"}],"type":"function"},{"constant":true,"inputs":[],"name":"counter","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"amt","type":"uint256"}],"name":"increment","outputs":[{"name":"result","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"a","type":"int256"},{"name":"b","type":"int256"}],"name":"add","outputs":[{"name":"result","type":"int256"}],"type":"function"},{"constant":false,"inputs":[],"name":"increment","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":false,"inputs":[{"name":"a","type":"int256"}],"name":"multiply7","outputs":[{"name":"result","type":"int256"}],"type":"function"},{"anonymous":false,"inputs":[{"indexed":false,"name":"value","type":"uint256"}],"name":"Increased","type":"event"}]')  # noqa: E501


@pytest.fixture(scope="session")
def MATH_CODE():
    return CONTRACT_CODE


@pytest.fixture(scope="session")
def MATH_RUNTIME():
    return CONTRACT_RUNTIME


@pytest.fixture(scope="session")
def MATH_ABI():
    return CONTRACT_ABI


@pytest.fixture()
def MathContract(web3, MATH_ABI, MATH_CODE, MATH_RUNTIME):
    return web3.eth.contract(
        abi=MATH_ABI,
        bytecode=MATH_CODE,
        bytecode_runtime=MATH_RUNTIME,
    )


CONTRACT_SIMPLE_CONSTRUCTOR_CODE = '0x60606040526003600055602c8060156000396000f3606060405260e060020a600035046373d4a13a8114601a575b005b602260005481565b6060908152602090f3'  # noqa: E501
CONTRACT_SIMPLE_CONSTRUCTOR_RUNTIME = '0x606060405260e060020a600035046373d4a13a8114601a575b005b602260005481565b6060908152602090f3'  # noqa: E501
CONTRACT_SIMPLE_CONSTRUCTOR_ABI = json.loads('[{"constant":true,"inputs":[],"name":"data","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"inputs":[],"type":"constructor"}]')  # noqa: E501


@pytest.fixture(scope="session")
def SIMPLE_CONSTRUCTOR_CODE():
    return CONTRACT_SIMPLE_CONSTRUCTOR_CODE


@pytest.fixture(scope="session")
def SIMPLE_CONSTRUCTOR_RUNTIME():
    return CONTRACT_SIMPLE_CONSTRUCTOR_RUNTIME


@pytest.fixture(scope="session")
def SIMPLE_CONSTRUCTOR_ABI():
    return CONTRACT_SIMPLE_CONSTRUCTOR_ABI


@pytest.fixture()
def SimpleConstructorContract(web3,
                              SIMPLE_CONSTRUCTOR_CODE,
                              SIMPLE_CONSTRUCTOR_RUNTIME,
                              SIMPLE_CONSTRUCTOR_ABI):
    return web3.eth.contract(
        abi=SIMPLE_CONSTRUCTOR_ABI,
        bytecode=SIMPLE_CONSTRUCTOR_CODE,
        bytecode_runtime=SIMPLE_CONSTRUCTOR_RUNTIME,
    )


CONTRACT_WITH_CONSTRUCTOR_ARGUMENTS_CODE = "0x60606040818152806066833960a09052516080516000918255600155603e908190602890396000f3606060405260e060020a600035046388ec134681146024578063d4c46c7614602c575b005b603460005481565b603460015481565b6060908152602090f3"  # noqa: E501
CONTRACT_WITH_CONSTRUCTOR_ARGUMENTS_RUNTIME = "0x606060405260e060020a600035046388ec134681146024578063d4c46c7614602c575b005b603460005481565b603460015481565b6060908152602090f3"  # noqa: E501
CONTRACT_WITH_CONSTRUCTOR_ARGUMENTS_ABI = json.loads('[{"constant":true,"inputs":[],"name":"data_a","outputs":[{"name":"","type":"uint256"}],"type":"function"},{"constant":true,"inputs":[],"name":"data_b","outputs":[{"name":"","type":"bytes32"}],"type":"function"},{"inputs":[{"name":"a","type":"uint256"},{"name":"b","type":"bytes32"}],"type":"constructor"}]')  # noqa: E501


@pytest.fixture()
def WITH_CONSTRUCTOR_ARGUMENTS_CODE():
    return CONTRACT_WITH_CONSTRUCTOR_ARGUMENTS_CODE


@pytest.fixture()
def WITH_CONSTRUCTOR_ARGUMENTS_RUNTIME():
    return CONTRACT_WITH_CONSTRUCTOR_ARGUMENTS_RUNTIME


@pytest.fixture()
def WITH_CONSTRUCTOR_ARGUMENTS_ABI():
    return CONTRACT_WITH_CONSTRUCTOR_ARGUMENTS_ABI


@pytest.fixture()
def WithConstructorArgumentsContract(web3,
                                     WITH_CONSTRUCTOR_ARGUMENTS_CODE,
                                     WITH_CONSTRUCTOR_ARGUMENTS_RUNTIME,
                                     WITH_CONSTRUCTOR_ARGUMENTS_ABI):
    return web3.eth.contract(
        abi=WITH_CONSTRUCTOR_ARGUMENTS_ABI,
        bytecode=WITH_CONSTRUCTOR_ARGUMENTS_CODE,
        bytecode_runtime=WITH_CONSTRUCTOR_ARGUMENTS_RUNTIME,
    )


@pytest.fixture()
def WithConstructorArgumentsContractStrict(w3_strict_abi,
                                           WITH_CONSTRUCTOR_ARGUMENTS_CODE,
                                           WITH_CONSTRUCTOR_ARGUMENTS_RUNTIME,
                                           WITH_CONSTRUCTOR_ARGUMENTS_ABI):
    return w3_strict_abi.eth.contract(
        abi=WITH_CONSTRUCTOR_ARGUMENTS_ABI,
        bytecode=WITH_CONSTRUCTOR_ARGUMENTS_CODE,
        bytecode_runtime=WITH_CONSTRUCTOR_ARGUMENTS_RUNTIME,
    )


CONTRACT_WITH_CONSTRUCTOR_ADDRESS_CODE = "0x6060604052604051602080607683395060806040525160008054600160a060020a031916821790555060428060346000396000f3606060405260e060020a600035046334664e3a8114601a575b005b603860005473ffffffffffffffffffffffffffffffffffffffff1681565b6060908152602090f3"  # noqa: E501
CONTRACT_WITH_CONSTRUCTOR_ADDRESS_RUNTIME = "0x606060405260e060020a600035046334664e3a8114601a575b005b603860005473ffffffffffffffffffffffffffffffffffffffff1681565b6060908152602090f3"  # noqa: E501
CONTRACT_WITH_CONSTRUCTOR_ADDRESS_ABI = json.loads('[{"constant":true,"inputs":[],"name":"testAddr","outputs":[{"name":"","type":"address"}],"type":"function"},{"inputs":[{"name":"_testAddr","type":"address"}],"type":"constructor"}]')  # noqa: E501


@pytest.fixture()
def WITH_CONSTRUCTOR_ADDRESS_CODE():
    return CONTRACT_WITH_CONSTRUCTOR_ADDRESS_CODE


@pytest.fixture()
def WITH_CONSTRUCTOR_ADDRESS_RUNTIME():
    return CONTRACT_WITH_CONSTRUCTOR_ADDRESS_RUNTIME


@pytest.fixture()
def WITH_CONSTRUCTOR_ADDRESS_ABI():
    return CONTRACT_WITH_CONSTRUCTOR_ADDRESS_ABI


@pytest.fixture()
def WithConstructorAddressArgumentsContract(web3,
                                            WITH_CONSTRUCTOR_ADDRESS_CODE,
                                            WITH_CONSTRUCTOR_ADDRESS_RUNTIME,
                                            WITH_CONSTRUCTOR_ADDRESS_ABI):
    return web3.eth.contract(
        abi=WITH_CONSTRUCTOR_ADDRESS_ABI,
        bytecode=WITH_CONSTRUCTOR_ADDRESS_CODE,
        bytecode_runtime=WITH_CONSTRUCTOR_ADDRESS_RUNTIME,
    )


@pytest.fixture()
def AddressReflectorContract(web3):
    return web3.eth.contract(
        abi=json.loads('[{"constant":true,"inputs":[{"name":"arg","type":"address"}],"name":"reflect","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"arg","type":"address[]"}],"name":"reflect","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"pure","type":"function"}]'),  # noqa: 501
        bytecode="6060604052341561000f57600080fd5b6101ca8061001e6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630b816c1614610048578063c04d11fc146100c157600080fd5b341561005357600080fd5b61007f600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610170565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100cc57600080fd5b61011960048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061017a565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561015c578082015181840152602081019050610141565b505050509050019250505060405180910390f35b6000819050919050565b61018261018a565b819050919050565b6020604051908101604052806000815250905600a165627a7a723058206b15d98a803b91327d94f943e9712291539701b2f7370e10f5873633941484930029",  # noqa: 501
        bytecode_runtime="60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630b816c1614610048578063c04d11fc146100c157600080fd5b341561005357600080fd5b61007f600480803573ffffffffffffffffffffffffffffffffffffffff16906020019091905050610170565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34156100cc57600080fd5b61011960048080359060200190820180359060200190808060200260200160405190810160405280939291908181526020018383602002808284378201915050505050509190505061017a565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561015c578082015181840152602081019050610141565b505050509050019250505060405180910390f35b6000819050919050565b61018261018a565b819050919050565b6020604051908101604052806000815250905600a165627a7a723058206b15d98a803b91327d94f943e9712291539701b2f7370e10f5873633941484930029",  # noqa: 501
    )


CONTRACT_STRING_CODE = "0x6060604052604051610496380380610496833981016040528051018060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10608d57805160ff19168380011785555b50607c9291505b8082111560ba57838155600101606b565b5050506103d8806100be6000396000f35b828001600101855582156064579182015b828111156064578251826000505591602001919060010190609e565b509056606060405260e060020a600035046320965255811461003c57806330de3cee1461009f5780633fa4f245146100c457806393a0935214610121575b005b6101c7600060608181528154602060026001831615610100026000190190921691909104601f810182900490910260a0908101604052608082815292939190828280156102605780601f1061023557610100808354040283529160200191610260565b6101c7600060609081526101a06040526101006080818152906102d860a03990505b90565b6101c760008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156102975780601f1061026c57610100808354040283529160200191610297565b60206004803580820135601f81018490049093026080908101604052606084815261003a946024939192918401918190838280828437509496505050505050508060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061029f57805160ff19168380011785555b506102cf9291505b808211156102d4578381556001016101b4565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156102275780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b820191906000526020600020905b81548152906001019060200180831161024357829003601f168201915b505050505090506100c1565b820191906000526020600020905b81548152906001019060200180831161027a57829003601f168201915b505050505081565b828001600101855582156101ac579182015b828111156101ac5782518260005055916020019190600101906102b1565b505050565b509056000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"  # noqa: E501

CONTRACT_STRING_RUNTIME = "0x606060405260e060020a600035046320965255811461003c57806330de3cee1461009f5780633fa4f245146100c457806393a0935214610121575b005b6101c7600060608181528154602060026001831615610100026000190190921691909104601f810182900490910260a0908101604052608082815292939190828280156102605780601f1061023557610100808354040283529160200191610260565b6101c7600060609081526101a06040526101006080818152906102d860a03990505b90565b6101c760008054602060026001831615610100026000190190921691909104601f810182900490910260809081016040526060828152929190828280156102975780601f1061026c57610100808354040283529160200191610297565b60206004803580820135601f81018490049093026080908101604052606084815261003a946024939192918401918190838280828437509496505050505050508060006000509080519060200190828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061029f57805160ff19168380011785555b506102cf9291505b808211156102d4578381556001016101b4565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156102275780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b820191906000526020600020905b81548152906001019060200180831161024357829003601f168201915b505050505090506100c1565b820191906000526020600020905b81548152906001019060200180831161027a57829003601f168201915b505050505081565b828001600101855582156101ac579182015b828111156101ac5782518260005055916020019190600101906102b1565b505050565b509056000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebfc0c1c2c3c4c5c6c7c8c9cacbcccdcecfd0d1d2d3d4d5d6d7d8d9dadbdcdddedfe0e1e2e3e4e5e6e7e8e9eaebecedeeeff0f1f2f3f4f5f6f7f8f9fafbfcfdfeff"  # noqa: E501

CONTRACT_STRING_ABI = json.loads('[{"constant":false,"inputs":[],"name":"getValue","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[],"name":"constValue","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"string"}],"type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"string"}],"name":"setValue","outputs":[],"type":"function"},{"inputs":[{"name":"_value","type":"string"}],"type":"constructor"}]')  # noqa: E501


@pytest.fixture()
def STRING_CODE():
    return CONTRACT_STRING_CODE


@pytest.fixture()
def STRING_RUNTIME():
    return CONTRACT_STRING_RUNTIME


@pytest.fixture()
def STRING_ABI():
    return CONTRACT_STRING_ABI


@pytest.fixture()
def STRING_CONTRACT(STRING_CODE, STRING_RUNTIME, STRING_ABI):
    return {
        'bytecode': STRING_CODE,
        'bytecode_runtime': STRING_RUNTIME,
        'abi': STRING_ABI,
    }


@pytest.fixture()
def StringContract(web3, STRING_CONTRACT):
    return web3.eth.contract(**STRING_CONTRACT)


CONTRACT_BYTES_CODE = "60606040526040805190810160405280600281526020017f01230000000000000000000000000000000000000000000000000000000000008152506000908051906020019061004f929190610096565b50341561005b57600080fd5b604051610723380380610723833981016040528080518201919050505b806001908051906020019061008e929190610116565b505b506101bb565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100d757805160ff1916838001178555610105565b82800160010185558215610105579182015b828111156101045782518255916020019190600101906100e9565b5b5090506101129190610196565b5090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061015757805160ff1916838001178555610185565b82800160010185558215610185579182015b82811115610184578251825591602001919060010190610169565b5b5090506101929190610196565b5090565b6101b891905b808211156101b457600081600090555060010161019c565b5090565b90565b610559806101ca6000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063209652551461005f57806330de3cee146100ee5780633fa4f2451461017d578063439970aa1461020c575b600080fd5b341561006a57600080fd5b610072610269565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100b35780820151818401525b602081019050610097565b50505050905090810190601f1680156100e05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100f957600080fd5b610101610312565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101425780820151818401525b602081019050610126565b50505050905090810190601f16801561016f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018857600080fd5b6101906103bb565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101d15780820151818401525b6020810190506101b5565b50505050905090810190601f1680156101fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561021757600080fd5b610267600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610459565b005b610271610474565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103075780601f106102dc57610100808354040283529160200191610307565b820191906000526020600020905b8154815290600101906020018083116102ea57829003601f168201915b505050505090505b90565b61031a610474565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103b05780601f10610385576101008083540402835291602001916103b0565b820191906000526020600020905b81548152906001019060200180831161039357829003601f168201915b505050505090505b90565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104515780601f1061042657610100808354040283529160200191610451565b820191906000526020600020905b81548152906001019060200180831161043457829003601f168201915b505050505081565b806001908051906020019061046f929190610488565b505b50565b602060405190810160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106104c957805160ff19168380011785556104f7565b828001600101855582156104f7579182015b828111156104f65782518255916020019190600101906104db565b5b5090506105049190610508565b5090565b61052a91905b8082111561052657600081600090555060010161050e565b5090565b905600a165627a7a723058203ff916ee91add6247b20793745d1c6a8d8dcaa49d8c84fbbabb5c966fd9b6fc90029"  # noqa: E501

CONTRACT_BYTES_RUNTIME = "60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063209652551461005f57806330de3cee146100ee5780633fa4f2451461017d578063439970aa1461020c575b600080fd5b341561006a57600080fd5b610072610269565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156100b35780820151818401525b602081019050610097565b50505050905090810190601f1680156100e05780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34156100f957600080fd5b610101610312565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101425780820151818401525b602081019050610126565b50505050905090810190601f16801561016f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561018857600080fd5b6101906103bb565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101d15780820151818401525b6020810190506101b5565b50505050905090810190601f1680156101fe5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b341561021757600080fd5b610267600480803590602001908201803590602001908080601f01602080910402602001604051908101604052809392919081815260200183838082843782019150505050505091905050610459565b005b610271610474565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103075780601f106102dc57610100808354040283529160200191610307565b820191906000526020600020905b8154815290600101906020018083116102ea57829003601f168201915b505050505090505b90565b61031a610474565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156103b05780601f10610385576101008083540402835291602001916103b0565b820191906000526020600020905b81548152906001019060200180831161039357829003601f168201915b505050505090505b90565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156104515780601f1061042657610100808354040283529160200191610451565b820191906000526020600020905b81548152906001019060200180831161043457829003601f168201915b505050505081565b806001908051906020019061046f929190610488565b505b50565b602060405190810160405280600081525090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106104c957805160ff19168380011785556104f7565b828001600101855582156104f7579182015b828111156104f65782518255916020019190600101906104db565b5b5090506105049190610508565b5090565b61052a91905b8082111561052657600081600090555060010161050e565b5090565b905600a165627a7a723058203ff916ee91add6247b20793745d1c6a8d8dcaa49d8c84fbbabb5c966fd9b6fc90029"  # noqa: E501

CONTRACT_BYTES_ABI = json.loads('[{"constant":false,"inputs":[],"name":"getValue","outputs":[{"name":"","type":"bytes"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"constValue","outputs":[{"name":"","type":"bytes"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"bytes"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"bytes"}],"name":"setValue","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"_value","type":"bytes"}],"payable":false,"type":"constructor"}]')  # noqa: E501


@pytest.fixture()
def BYTES_CODE():
    return CONTRACT_BYTES_CODE


@pytest.fixture()
def BYTES_RUNTIME():
    return CONTRACT_BYTES_RUNTIME


@pytest.fixture()
def BYTES_ABI():
    return CONTRACT_BYTES_ABI


@pytest.fixture()
def BYTES_CONTRACT(BYTES_CODE, BYTES_RUNTIME, BYTES_ABI):
    return {
        'bytecode': BYTES_CODE,
        'bytecode_runtime': BYTES_RUNTIME,
        'abi': BYTES_ABI,
    }


@pytest.fixture()
def BytesContract(web3, BYTES_CONTRACT):
    return web3.eth.contract(**BYTES_CONTRACT)


CONTRACT_BYTES32_CODE = "60606040527f0123012301230123012301230123012301230123012301230123012301230123600090600019169055341561003957600080fd5b6040516020806101e2833981016040528080519060200190919050505b80600181600019169055505b505b61016f806100736000396000f30060606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063209652551461005f57806330de3cee146100905780633fa4f245146100c157806358825b10146100f2575b600080fd5b341561006a57600080fd5b610072610119565b60405180826000191660001916815260200191505060405180910390f35b341561009b57600080fd5b6100a3610124565b60405180826000191660001916815260200191505060405180910390f35b34156100cc57600080fd5b6100d461012e565b60405180826000191660001916815260200191505060405180910390f35b34156100fd57600080fd5b610117600480803560001916906020019091905050610134565b005b600060015490505b90565b6000805490505b90565b60015481565b80600181600019169055505b505600a165627a7a7230582043b15c20378b1603d330561258ccf291d08923a4c25fa8af0d590a010a6322180029"  # noqa: E501

CONTRACT_BYTES32_RUNTIME = "60606040526000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063209652551461005f57806330de3cee146100905780633fa4f245146100c157806358825b10146100f2575b600080fd5b341561006a57600080fd5b610072610119565b60405180826000191660001916815260200191505060405180910390f35b341561009b57600080fd5b6100a3610124565b60405180826000191660001916815260200191505060405180910390f35b34156100cc57600080fd5b6100d461012e565b60405180826000191660001916815260200191505060405180910390f35b34156100fd57600080fd5b610117600480803560001916906020019091905050610134565b005b600060015490505b90565b6000805490505b90565b60015481565b80600181600019169055505b505600a165627a7a7230582043b15c20378b1603d330561258ccf291d08923a4c25fa8af0d590a010a6322180029"  # noqa: E501

CONTRACT_BYTES32_ABI = json.loads('[{"constant":false,"inputs":[],"name":"getValue","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[],"name":"constValue","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":true,"inputs":[],"name":"value","outputs":[{"name":"","type":"bytes32"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"_value","type":"bytes32"}],"name":"setValue","outputs":[],"payable":false,"type":"function"},{"inputs":[{"name":"_value","type":"bytes32"}],"payable":false,"type":"constructor"}]')  # noqa: E501


@pytest.fixture()
def BYTES32_CODE():
    return CONTRACT_BYTES32_CODE


@pytest.fixture()
def BYTES32_RUNTIME():
    return CONTRACT_BYTES32_RUNTIME


@pytest.fixture()
def BYTES32_ABI():
    return CONTRACT_BYTES32_ABI


@pytest.fixture()
def BYTES32_CONTRACT(BYTES32_CODE, BYTES32_RUNTIME, BYTES32_ABI):
    return {
        'bytecode': BYTES32_CODE,
        'bytecode_runtime': BYTES32_RUNTIME,
        'abi': BYTES32_ABI,
    }


@pytest.fixture()
def Bytes32Contract(web3, BYTES32_CONTRACT):
    return web3.eth.contract(**BYTES32_CONTRACT)


@pytest.fixture()
def EMITTER_CODE():
    return CONTRACT_EMITTER_CODE


@pytest.fixture()
def EMITTER_RUNTIME():
    return CONTRACT_EMITTER_RUNTIME


@pytest.fixture()
def EMITTER_ABI():
    return CONTRACT_EMITTER_ABI


@pytest.fixture()
def EMITTER(EMITTER_CODE,
            EMITTER_RUNTIME,
            EMITTER_ABI):
    return {
        'bytecode': EMITTER_CODE,
        'bytecode_runtime': EMITTER_RUNTIME,
        'abi': EMITTER_ABI,
    }


@pytest.fixture()
def StrictEmitter(w3_strict_abi, EMITTER):
    w3 = w3_strict_abi
    return w3.eth.contract(**EMITTER)


@pytest.fixture()
def strict_emitter(w3_strict_abi,
                   StrictEmitter,
                   wait_for_transaction,
                   wait_for_block,
                   address_conversion_func):
    w3 = w3_strict_abi

    wait_for_block(w3)
    deploy_txn_hash = StrictEmitter.constructor().transact(
        {'from': w3.eth.coinbase, 'gas': 1000000}
    )
    deploy_receipt = wait_for_transaction(w3, deploy_txn_hash)
    contract_address = address_conversion_func(deploy_receipt['contractAddress'])

    bytecode = w3.eth.getCode(contract_address)
    assert bytecode == StrictEmitter.bytecode_runtime
    emitter_contract = StrictEmitter(address=contract_address)
    assert emitter_contract.address == contract_address
    return emitter_contract


@pytest.fixture()
def EVENT_CONTRACT_CODE():
    return EVNT_CONTRACT_CODE


@pytest.fixture()
def EVENT_CONTRACT_RUNTIME():
    return EVNT_CONTRACT_RUNTIME


@pytest.fixture()
def EVENT_CONTRACT_ABI():
    return EVNT_CONTRACT_ABI


@pytest.fixture()
def EVENT_CONTRACT(
        EVENT_CONTRACT_CODE,
        EVENT_CONTRACT_RUNTIME,
        EVENT_CONTRACT_ABI):
    return {
        'bytecode': EVENT_CONTRACT_CODE,
        'bytecode_runtime': EVENT_CONTRACT_RUNTIME,
        'abi': EVENT_CONTRACT_ABI,
    }


@pytest.fixture()
def EventContract(web3_empty, EVENT_CONTRACT):
    web3 = web3_empty
    return web3.eth.contract(**EVENT_CONTRACT)


@pytest.fixture()
def event_contract(
        web3_empty,
        EventContract,
        wait_for_transaction,
        wait_for_block,
        address_conversion_func):

    web3 = web3_empty

    wait_for_block(web3)
    deploy_txn_hash = EventContract.constructor().transact({
        'from': web3.eth.coinbase, 'gas': 1000000
    })
    deploy_receipt = wait_for_transaction(web3, deploy_txn_hash)
    contract_address = address_conversion_func(deploy_receipt['contractAddress'])

    bytecode = web3.eth.getCode(contract_address)
    assert bytecode == EventContract.bytecode_runtime
    event_contract = EventContract(address=contract_address)
    assert event_contract.address == contract_address
    return event_contract


@pytest.fixture()
def INDEXED_EVENT_CONTRACT_CODE():
    return IND_EVENT_CONTRACT_CODE


@pytest.fixture()
def INDEXED_EVENT_CONTRACT_RUNTIME():
    return IND_EVENT_CONTRACT_RUNTIME


@pytest.fixture()
def INDEXED_EVENT_CONTRACT_ABI():
    return IND_EVENT_CONTRACT_ABI


@pytest.fixture()
def INDEXED_EVENT_CONTRACT(
        INDEXED_EVENT_CONTRACT_CODE,
        INDEXED_EVENT_CONTRACT_RUNTIME,
        INDEXED_EVENT_CONTRACT_ABI):
    return {
        'bytecode': INDEXED_EVENT_CONTRACT_CODE,
        'bytecode_runtime': INDEXED_EVENT_CONTRACT_RUNTIME,
        'abi': INDEXED_EVENT_CONTRACT_ABI,
    }


@pytest.fixture()
def IndexedEventContract(web3_empty, INDEXED_EVENT_CONTRACT):
    web3 = web3_empty
    return web3.eth.contract(**INDEXED_EVENT_CONTRACT)


@pytest.fixture()
def indexed_event(
        web3_empty,
        IndexedEventContract,
        wait_for_transaction,
        wait_for_block,
        address_conversion_func):

    web3 = web3_empty

    wait_for_block(web3)
    deploy_txn_hash = IndexedEventContract.constructor().transact({
        'from': web3.eth.coinbase,
        'gas': 1000000
    })
    deploy_receipt = wait_for_transaction(web3, deploy_txn_hash)
    contract_address = address_conversion_func(deploy_receipt['contractAddress'])

    bytecode = web3.eth.getCode(contract_address)
    assert bytecode == IndexedEventContract.bytecode_runtime
    indexed_event_contract = IndexedEventContract(address=contract_address)
    assert indexed_event_contract.address == contract_address
    return indexed_event_contract


CONTRACT_ARRAYS_SOURCE = """
    contract ArraysContract {

        bytes32[] public bytes32Value;
        bytes32[] public bytes32ConstValue;
        byte[] public byteValue;
        byte[] public byteConstValue;

        function ArraysContract(bytes32[] _bytes32Value, byte[] _byteValue) {
            bytes32Value = _bytes32Value;
            byteValue = _byteValue;
            bytes32ConstValue = [keccak256('A'), keccak256('B')];
            byteConstValue = [bytes1(0), bytes1(1)];
        }

        function setBytes32Value(bytes32[] _bytes32Value) {
            bytes32Value = _bytes32Value;
        }

        function getBytes32Value() returns (bytes32[]) {
            return bytes32Value;
        }

        function getBytes32ConstValue() returns (bytes32[]) {
            return bytes32ConstValue;
        }

        function setByteValue(byte[] _byteValue) {
            byteValue = _byteValue;
        }

        function getByteValue() returns (byte[]) {
            return byteValue;
        }

        function getByteConstValue() returns (byte[]) {
            return byteConstValue;
        }
}
"""


CONTRACT_ARRAYS_CODE = "606060405234156200001057600080fd5b60405162000e6238038062000e628339810160405280805182019190602001805182019190505081600090805190602001906200004f92919062000209565b5080600290805190602001906200006892919062000261565b50604080519081016040528060405180807f4100000000000000000000000000000000000000000000000000000000000000815250600101905060405180910390206000191660001916815260200160405180807f420000000000000000000000000000000000000000000000000000000000000081525060010190506040518091039020600019166000191681525060019060026200010a9291906200032f565b50604080519081016040528060007f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200160017f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff191681525060039060026200020092919062000387565b505050620004b0565b8280548282559060005260206000209081019282156200024e579160200282015b828111156200024d5782518290600019169055916020019190600101906200022a565b5b5090506200025d919062000455565b5090565b82805482825590600052602060002090601f016020900481019282156200031c5791602002820160005b83821115620002eb57835183826101000a81548160ff02191690837f01000000000000000000000000000000000000000000000000000000000000009004021790555092602001926001016020816000010492830192600103026200028b565b80156200031a5782816101000a81549060ff0219169055600101602081600001049283019260010302620002eb565b505b5090506200032b91906200047d565b5090565b82805482825590600052602060002090810192821562000374579160200282015b828111156200037357825182906000191690559160200191906001019062000350565b5b50905062000383919062000455565b5090565b82805482825590600052602060002090601f01602090048101928215620004425791602002820160005b838211156200041157835183826101000a81548160ff02191690837f0100000000000000000000000000000000000000000000000000000000000000900402179055509260200192600101602081600001049283019260010302620003b1565b8015620004405782816101000a81549060ff021916905560010160208160000104928301926001030262000411565b505b5090506200045191906200047d565b5090565b6200047a91905b80821115620004765760008160009055506001016200045c565b5090565b90565b620004ad91905b80821115620004a957600081816101000a81549060ff02191690555060010162000484565b5090565b90565b6109a280620004c06000396000f300606060405236156100a2576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630afe5e33146100a757806312c9dcc8146101115780631579bf661461018c5780633ddcea2f146101f657806351b4878814610250578063542d83de1461028f578063605ba271146102ce5780638abe51fd14610338578063962e450c146103a2578063bb69679b1461041d575b600080fd5b34156100b257600080fd5b6100ba610477565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156100fd5780820151818401526020810190506100e2565b505050509050019250505060405180910390f35b341561011c57600080fd5b61013260048080359060200190919050506104d9565b60405180827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b341561019757600080fd5b61019f61052b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156101e25780820151818401526020810190506101c7565b505050509050019250505060405180910390f35b341561020157600080fd5b61024e6004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506105ed565b005b341561025b57600080fd5b6102716004808035906020019091905050610607565b60405180826000191660001916815260200191505060405180910390f35b341561029a57600080fd5b6102b0600480803590602001909190505061062b565b60405180826000191660001916815260200191505060405180910390f35b34156102d957600080fd5b6102e161064f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610324578082015181840152602081019050610309565b505050509050019250505060405180910390f35b341561034357600080fd5b61034b6106b1565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561038e578082015181840152602081019050610373565b505050509050019250505060405180910390f35b34156103ad57600080fd5b6103c36004808035906020019091905050610773565b60405180827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b341561042857600080fd5b6104756004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506107c5565b005b61047f6107df565b60018054806020026020016040519081016040528092919081815260200182805480156104cf57602002820191906000526020600020905b815460001916815260200190600101908083116104b7575b5050505050905090565b6002818154811015156104e857fe5b9060005260206000209060209182820401919006915054906101000a90047f01000000000000000000000000000000000000000000000000000000000000000281565b6105336107f3565b60038054806020026020016040519081016040528092919081815260200182805480156105e357602002820191906000526020600020906000905b82829054906101000a90047f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906001019060208260000104928301926001038202915080841161056e5790505b5050505050905090565b8060029080519060200190610603929190610807565b5050565b60018181548110151561061657fe5b90600052602060002090016000915090505481565b60008181548110151561063a57fe5b90600052602060002090016000915090505481565b6106576107df565b60008054806020026020016040519081016040528092919081815260200182805480156106a757602002820191906000526020600020905b8154600019168152602001906001019080831161068f575b5050505050905090565b6106b96107f3565b600280548060200260200160405190810160405280929190818152602001828054801561076957602002820191906000526020600020906000905b82829054906101000a90047f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600101906020826000010492830192600103820291508084116106f45790505b5050505050905090565b60038181548110151561078257fe5b9060005260206000209060209182820401919006915054906101000a90047f01000000000000000000000000000000000000000000000000000000000000000281565b80600090805190602001906107db9291906108ce565b5050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b82805482825590600052602060002090601f016020900481019282156108bd5791602002820160005b8382111561088e57835183826101000a81548160ff02191690837f0100000000000000000000000000000000000000000000000000000000000000900402179055509260200192600101602081600001049283019260010302610830565b80156108bb5782816101000a81549060ff021916905560010160208160000104928301926001030261088e565b505b5090506108ca9190610921565b5090565b828054828255906000526020600020908101928215610910579160200282015b8281111561090f5782518290600019169055916020019190600101906108ee565b5b50905061091d9190610951565b5090565b61094e91905b8082111561094a57600081816101000a81549060ff021916905550600101610927565b5090565b90565b61097391905b8082111561096f576000816000905550600101610957565b5090565b905600a165627a7a72305820d0caf89bd0d39b343a907ac9d0f0b9bcddb1b8dc910706160d9d26fdc552afa40029"  # noqa: E501

CONTRACT_ARRAYS_RUNTIME = "0x606060405236156100a2576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff1680630afe5e33146100a757806312c9dcc8146101115780631579bf661461018c5780633ddcea2f146101f657806351b4878814610250578063542d83de1461028f578063605ba271146102ce5780638abe51fd14610338578063962e450c146103a2578063bb69679b1461041d575b600080fd5b34156100b257600080fd5b6100ba610477565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156100fd5780820151818401526020810190506100e2565b505050509050019250505060405180910390f35b341561011c57600080fd5b61013260048080359060200190919050506104d9565b60405180827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b341561019757600080fd5b61019f61052b565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b838110156101e25780820151818401526020810190506101c7565b505050509050019250505060405180910390f35b341561020157600080fd5b61024e6004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506105ed565b005b341561025b57600080fd5b6102716004808035906020019091905050610607565b60405180826000191660001916815260200191505060405180910390f35b341561029a57600080fd5b6102b0600480803590602001909190505061062b565b60405180826000191660001916815260200191505060405180910390f35b34156102d957600080fd5b6102e161064f565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b83811015610324578082015181840152602081019050610309565b505050509050019250505060405180910390f35b341561034357600080fd5b61034b6106b1565b6040518080602001828103825283818151815260200191508051906020019060200280838360005b8381101561038e578082015181840152602081019050610373565b505050509050019250505060405180910390f35b34156103ad57600080fd5b6103c36004808035906020019091905050610773565b60405180827effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200191505060405180910390f35b341561042857600080fd5b6104756004808035906020019082018035906020019080806020026020016040519081016040528093929190818152602001838360200280828437820191505050505050919050506107c5565b005b61047f6107df565b60018054806020026020016040519081016040528092919081815260200182805480156104cf57602002820191906000526020600020905b815460001916815260200190600101908083116104b7575b5050505050905090565b6002818154811015156104e857fe5b9060005260206000209060209182820401919006915054906101000a90047f01000000000000000000000000000000000000000000000000000000000000000281565b6105336107f3565b60038054806020026020016040519081016040528092919081815260200182805480156105e357602002820191906000526020600020906000905b82829054906101000a90047f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff19168152602001906001019060208260000104928301926001038202915080841161056e5790505b5050505050905090565b8060029080519060200190610603929190610807565b5050565b60018181548110151561061657fe5b90600052602060002090016000915090505481565b60008181548110151561063a57fe5b90600052602060002090016000915090505481565b6106576107df565b60008054806020026020016040519081016040528092919081815260200182805480156106a757602002820191906000526020600020905b8154600019168152602001906001019080831161068f575b5050505050905090565b6106b96107f3565b600280548060200260200160405190810160405280929190818152602001828054801561076957602002820191906000526020600020906000905b82829054906101000a90047f0100000000000000000000000000000000000000000000000000000000000000027effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190600101906020826000010492830192600103820291508084116106f45790505b5050505050905090565b60038181548110151561078257fe5b9060005260206000209060209182820401919006915054906101000a90047f01000000000000000000000000000000000000000000000000000000000000000281565b80600090805190602001906107db9291906108ce565b5050565b602060405190810160405280600081525090565b602060405190810160405280600081525090565b82805482825590600052602060002090601f016020900481019282156108bd5791602002820160005b8382111561088e57835183826101000a81548160ff02191690837f0100000000000000000000000000000000000000000000000000000000000000900402179055509260200192600101602081600001049283019260010302610830565b80156108bb5782816101000a81549060ff021916905560010160208160000104928301926001030261088e565b505b5090506108ca9190610921565b5090565b828054828255906000526020600020908101928215610910579160200282015b8281111561090f5782518290600019169055916020019190600101906108ee565b5b50905061091d9190610951565b5090565b61094e91905b8082111561094a57600081816101000a81549060ff021916905550600101610927565b5090565b90565b61097391905b8082111561096f576000816000905550600101610957565b5090565b905600a165627a7a72305820d0caf89bd0d39b343a907ac9d0f0b9bcddb1b8dc910706160d9d26fdc552afa40029"  # noqa: E501

CONTRACT_ARRAYS_ABI = json.loads('[{"constant": false, "inputs": [], "name": "getBytes32ConstValue", "outputs": [{"name": "", "type": "bytes32[]"}], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [{"name": "", "type": "uint256"}], "name": "byteValue", "outputs": [{"name": "", "type": "bytes1"}], "payable": false, "stateMutability": "view", "type": "function"}, {"constant": false, "inputs": [], "name": "getByteConstValue", "outputs": [{"name": "", "type": "bytes1[]"}], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": false, "inputs": [{"name": "_byteValue", "type": "bytes1[]"}], "name": "setByteValue", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [{"name": "", "type": "uint256"}], "name": "bytes32ConstValue", "outputs": [{"name": "", "type": "bytes32"}], "payable": false, "stateMutability": "view", "type": "function"}, {"constant": true, "inputs": [{"name": "", "type": "uint256"}], "name": "bytes32Value", "outputs": [{"name": "", "type": "bytes32"}], "payable": false, "stateMutability": "view", "type": "function"}, {"constant": false, "inputs": [], "name": "getBytes32Value", "outputs": [{"name": "", "type": "bytes32[]"}], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": false, "inputs": [], "name": "getByteValue", "outputs": [{"name": "", "type": "bytes1[]"}], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"constant": true, "inputs": [{"name": "", "type": "uint256"}], "name": "byteConstValue", "outputs": [{"name": "", "type": "bytes1"}], "payable": false, "stateMutability": "view", "type": "function"}, {"constant": false, "inputs": [{"name": "_bytes32Value", "type": "bytes32[]"}], "name": "setBytes32Value", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function"}, {"inputs": [{"name": "_bytes32Value", "type": "bytes32[]"}, {"name": "_byteValue", "type": "bytes1[]"}], "payable": false, "stateMutability": "nonpayable", "type": "constructor"}]')  # noqa: E501


@pytest.fixture()
def ARRAYS_CODE():
    return CONTRACT_ARRAYS_CODE


@pytest.fixture()
def ARRAYS_RUNTIME():
    return CONTRACT_ARRAYS_RUNTIME


@pytest.fixture()
def ARRAYS_ABI():
    return CONTRACT_ARRAYS_ABI


@pytest.fixture()
def ARRAYS_CONTRACT(ARRAYS_CODE,
                    ARRAYS_RUNTIME,
                    ARRAYS_ABI):
    return {
        'bytecode': ARRAYS_CODE,
        'bytecode_runtime': ARRAYS_RUNTIME,
        'abi': ARRAYS_ABI,
    }


@pytest.fixture()
def ArraysContract(web3, ARRAYS_CONTRACT):
    return web3.eth.contract(**ARRAYS_CONTRACT)


@pytest.fixture()
def StrictArraysContract(w3_strict_abi, ARRAYS_CONTRACT):
    return w3_strict_abi.eth.contract(**ARRAYS_CONTRACT)


CONTRACT_PAYABLE_TESTER_SOURCE = """
contract PayableTester {
  bool public wasCalled;

  function doNoValueCall() public {
    wasCalled = true;
  }
}
"""

CONTRACT_PAYABLE_TESTER_CODE = "608060405234801561001057600080fd5b5060e88061001f6000396000f3006080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c680362214604e578063e4cb8f5c14607a575b600080fd5b348015605957600080fd5b506060608e565b604051808215151515815260200191505060405180910390f35b348015608557600080fd5b50608c60a0565b005b6000809054906101000a900460ff1681565b60016000806101000a81548160ff0219169083151502179055505600a165627a7a723058205362c7376eda918b0dc3a75d0ffab904a241c9b10b68d5268af6ca405242303e0029"  # noqa: E501

CONTRACT_PAYABLE_TESTER_RUNTIME = "6080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff168063c680362214604e578063e4cb8f5c14607a575b600080fd5b348015605957600080fd5b506060608e565b604051808215151515815260200191505060405180910390f35b348015608557600080fd5b50608c60a0565b005b6000809054906101000a900460ff1681565b60016000806101000a81548160ff0219169083151502179055505600a165627a7a723058205362c7376eda918b0dc3a75d0ffab904a241c9b10b68d5268af6ca405242303e0029"  # noqa: E501

CONTRACT_PAYABLE_TESTER_ABI = json.loads('[{"constant": true, "inputs": [], "name": "wasCalled", "outputs": [{"name": "", "type": "bool"}], "payable": false, "stateMutability": "view", "type": "function"}, {"constant": false, "inputs": [], "name": "doNoValueCall", "outputs": [], "payable": false, "stateMutability": "nonpayable", "type": "function"}]')  # noqa: E501


@pytest.fixture()
def PAYABLE_TESTER_CODE():
    return CONTRACT_PAYABLE_TESTER_CODE


@pytest.fixture()
def PAYABLE_TESTER_RUNTIME():
    return CONTRACT_PAYABLE_TESTER_RUNTIME


@pytest.fixture()
def PAYABLE_TESTER_ABI():
    return CONTRACT_PAYABLE_TESTER_ABI


@pytest.fixture()
def PAYABLE_TESTER_CONTRACT(PAYABLE_TESTER_CODE,
                            PAYABLE_TESTER_RUNTIME,
                            PAYABLE_TESTER_ABI):
    return {
        'bytecode': PAYABLE_TESTER_CODE,
        'bytecode_runtime': PAYABLE_TESTER_RUNTIME,
        'abi': PAYABLE_TESTER_ABI,
    }


@pytest.fixture()
def PayableTesterContract(web3, PAYABLE_TESTER_CONTRACT):
    return web3.eth.contract(**PAYABLE_TESTER_CONTRACT)


# no matter the function selector, this will return back the 32 bytes of data supplied
CONTRACT_REFLECTION_CODE = (
    "0x610011566020600460003760206000f3005b61000461001103610004600039610004610011036000f3"
)

# reference source used to generate it:
LLL_SOURCE = "['seq', ['return', 0, ['lll', ['seq', ['calldatacopy', 0, 4, 32], ['return', 0, 32], 'stop' ], 0]]])"  # noqa: E501

CONTRACT_FIXED_ABI = [
    {
        "type": "function",
        "constant": False,
        "inputs": [{"type": "fixed8x1"}],
        "name": "reflect",
        "outputs": [{"type": "fixed8x1"}],
    },
    {
        "type": "function",
        "constant": False,
        "inputs": [{"type": "ufixed256x80"}],
        "name": "reflect",
        "outputs": [{"type": "ufixed256x80"}],
    },
    {
        "type": "function",
        "constant": False,
        "inputs": [{"type": "ufixed256x1"}],
        "name": "reflect",
        "outputs": [{"type": "ufixed256x1"}],
    },
    {
        "type": "function",
        "constant": False,
        "inputs": [{"type": "ufixed8x1"}],
        "name": "reflect_short_u",
        "outputs": [{"type": "ufixed8x1"}],
    },
]


@pytest.fixture
def FixedReflectionContract(web3):
    return web3.eth.contract(abi=CONTRACT_FIXED_ABI, bytecode=CONTRACT_REFLECTION_CODE)


@pytest.fixture()
def FALLBACK_FUNCTION_CODE():
    return CONTRACT_FALLBACK_FUNCTION_CODE


@pytest.fixture()
def FALLBACK_FUNCTION_RUNTIME():
    return CONTRACT_FALLBACK_FUNCTION_RUNTIME


@pytest.fixture()
def FALLBACK_FUNCTION_ABI():
    return CONTRACT_FALLBACK_FUNCTION_ABI


@pytest.fixture()
def FALLBACK_FUNCTION_CONTRACT(FALLBACK_FUNCTION_CODE,
                               FALLBACK_FUNCTION_RUNTIME,
                               FALLBACK_FUNCTION_ABI):
    return {
        'bytecode': FALLBACK_FUNCTION_CODE,
        'bytecode_runtime': FALLBACK_FUNCTION_RUNTIME,
        'abi': FALLBACK_FUNCTION_ABI,
    }


@pytest.fixture()
def FallbackFunctionContract(web3, FALLBACK_FUNCTION_CONTRACT):
    return web3.eth.contract(**FALLBACK_FUNCTION_CONTRACT)


@pytest.fixture()
def RECEIVE_FUNCTION_CODE():
    return CONTRACT_RECEIVE_FUNCTION_CODE


@pytest.fixture()
def RECEIVE_FUNCTION_RUNTIME():
    return CONTRACT_RECEIVE_FUNCTION_RUNTIME


@pytest.fixture()
def RECEIVE_FUNCTION_ABI():
    return CONTRACT_RECEIVE_FUNCTION_ABI


@pytest.fixture()
def RECEIVE_FUNCTION_CONTRACT(RECEIVE_FUNCTION_CODE,
                              RECEIVE_FUNCTION_RUNTIME,
                              RECEIVE_FUNCTION_ABI):
    return {
        'bytecode': RECEIVE_FUNCTION_CODE,
        'bytecode_runtime': RECEIVE_FUNCTION_RUNTIME,
        'abi': RECEIVE_FUNCTION_ABI,
    }


@pytest.fixture()
def NoReceiveFunctionContract(web3, NO_RECEIVE_FUNCTION_CONTRACT):
    return web3.eth.contract(**NO_RECEIVE_FUNCTION_CONTRACT)


@pytest.fixture()
def NO_RECEIVE_FUNCTION_CODE():
    return CONTRACT_NO_RECEIVE_FUNCTION_CODE


@pytest.fixture()
def NO_RECEIVE_FUNCTION_RUNTIME():
    return CONTRACT_NO_RECEIVE_FUNCTION_RUNTIME


@pytest.fixture()
def NO_RECEIVE_FUNCTION_ABI():
    return CONTRACT_NO_RECEIVE_FUNCTION_ABI


@pytest.fixture()
def NO_RECEIVE_FUNCTION_CONTRACT(NO_RECEIVE_FUNCTION_CODE,
                                 NO_RECEIVE_FUNCTION_RUNTIME,
                                 NO_RECEIVE_FUNCTION_ABI):
    return {
        'bytecode': NO_RECEIVE_FUNCTION_CODE,
        'bytecode_runtime': NO_RECEIVE_FUNCTION_RUNTIME,
        'abi': NO_RECEIVE_FUNCTION_ABI,
    }


@pytest.fixture()
def ReceiveFunctionContract(web3, RECEIVE_FUNCTION_CONTRACT):
    return web3.eth.contract(**RECEIVE_FUNCTION_CONTRACT)


CONTRACT_CALLER_TESTER_SOURCE = """
contract CallerTester {
  int public count;

  function add(int256 a, int256 b) public payable returns (int256) {
    return a + b;
  }

  function increment() public returns (int256) {
    return count += 1;
  }

  function counter() public payable returns (int256) {
    return count;
  }

  function returnMeta() public payable returns (address, bytes memory, uint256, uint, uint) {
    return (msg.sender, msg.data, gasleft(), msg.value, block.number);
  }
}
"""


CONTRACT_CALLER_TESTER_CODE = "608060405234801561001057600080fd5b50610241806100206000396000f3fe608060405260043610610066577c0100000000000000000000000000000000000000000000000000000000600035046306661abd811461006b57806361bc221a14610092578063a5f3c23b1461009a578063c7fa7d66146100bd578063d09de08a14610185575b600080fd5b34801561007757600080fd5b5061008061019a565b60408051918252519081900360200190f35b6100806101a0565b610080600480360360408110156100b057600080fd5b50803590602001356101a6565b6100c56101aa565b604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019080838360005b8381101561014657818101518382015260200161012e565b50505050905090810190601f1680156101735780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b34801561019157600080fd5b50610080610207565b60005481565b60005490565b0190565b600060606000806000336000365a344385955084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250989e929d50949b5092995090975095505050505050565b60008054600101908190559056fea165627a7a72305820ffe1620e420efa326b9c5e4ef9f93cac71cf986196246c7966d71a39259899b10029"  # noqa: E501


CONTRACT_CALLER_TESTER_RUNTIME = "608060405260043610610066577c0100000000000000000000000000000000000000000000000000000000600035046306661abd811461006b57806361bc221a14610092578063a5f3c23b1461009a578063c7fa7d66146100bd578063d09de08a14610185575b600080fd5b34801561007757600080fd5b5061008061019a565b60408051918252519081900360200190f35b6100806101a0565b610080600480360360408110156100b057600080fd5b50803590602001356101a6565b6100c56101aa565b604051808673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200180602001858152602001848152602001838152602001828103825286818151815260200191508051906020019080838360005b8381101561014657818101518382015260200161012e565b50505050905090810190601f1680156101735780820380516001836020036101000a031916815260200191505b50965050505050505060405180910390f35b34801561019157600080fd5b50610080610207565b60005481565b60005490565b0190565b600060606000806000336000365a344385955084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250989e929d50949b5092995090975095505050505050565b60008054600101908190559056fea165627a7a72305820ffe1620e420efa326b9c5e4ef9f93cac71cf986196246c7966d71a39259899b10029"  # noqa: E501


CONTRACT_CALLER_TESTER_ABI = json.loads('[ { "constant": true, "inputs": [], "name": "count", "outputs": [ { "name": "", "type": "int256" } ], "payable": false, "stateMutability": "view", "type": "function" }, { "constant": false, "inputs": [], "name": "counter", "outputs": [ { "name": "", "type": "int256" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "constant": false, "inputs": [ { "name": "a", "type": "int256" }, { "name": "b", "type": "int256" } ], "name": "add", "outputs": [ { "name": "", "type": "int256" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "constant": false, "inputs": [], "name": "returnMeta", "outputs": [ { "name": "", "type": "address" }, { "name": "", "type": "bytes" }, { "name": "", "type": "uint256" }, { "name": "", "type": "uint256" }, { "name": "", "type": "uint256" } ], "payable": true, "stateMutability": "payable", "type": "function" }, { "constant": false, "inputs": [], "name": "increment", "outputs": [ { "name": "", "type": "int256" } ], "payable": false, "stateMutability": "nonpayable", "type": "function" } ]')  # noqa: E501


@pytest.fixture()
def CALLER_TESTER_CODE():
    return CONTRACT_CALLER_TESTER_CODE


@pytest.fixture()
def CALLER_TESTER_RUNTIME():
    return CONTRACT_CALLER_TESTER_RUNTIME


@pytest.fixture()
def CALLER_TESTER_ABI():
    return CONTRACT_CALLER_TESTER_ABI


@pytest.fixture()
def CALLER_TESTER_CONTRACT(CALLER_TESTER_CODE,
                           CALLER_TESTER_RUNTIME,
                           CALLER_TESTER_ABI):
    return {
        'bytecode': CALLER_TESTER_CODE,
        'bytecode_runtime': CALLER_TESTER_RUNTIME,
        'abi': CALLER_TESTER_ABI,
    }


@pytest.fixture()
def CallerTesterContract(web3, CALLER_TESTER_CONTRACT):
    return web3.eth.contract(**CALLER_TESTER_CONTRACT)


class LogFunctions:
    LogAnonymous = 0
    LogNoArguments = 1
    LogSingleArg = 2
    LogDoubleArg = 3
    LogTripleArg = 4
    LogQuadrupleArg = 5
    LogSingleAnonymous = 6
    LogSingleWithIndex = 7
    LogDoubleAnonymous = 8
    LogDoubleWithIndex = 9
    LogTripleWithIndex = 10
    LogQuadrupleWithIndex = 11
    LogBytes = 12


@pytest.fixture()
def emitter_event_ids():
    return LogFunctions


def _encode_to_topic(event_signature):
    return event_signature_to_log_topic(event_signature)


class LogTopics:
    LogAnonymous = _encode_to_topic("LogAnonymous()")
    LogNoArguments = _encode_to_topic("LogNoArguments()")
    LogSingleArg = _encode_to_topic("LogSingleArg(uint256)")
    LogSingleAnonymous = _encode_to_topic("LogSingleAnonymous(uint256)")
    LogSingleWithIndex = _encode_to_topic("LogSingleWithIndex(uint256)")
    LogDoubleArg = _encode_to_topic("LogDoubleArg(uint256,uint256)")
    LogDoubleAnonymous = _encode_to_topic("LogDoubleAnonymous(uint256,uint256)")
    LogDoubleWithIndex = _encode_to_topic("LogDoubleWithIndex(uint256,uint256)")
    LogTripleArg = _encode_to_topic("LogTripleArg(uint256,uint256,uint256)")
    LogTripleWithIndex = _encode_to_topic("LogTripleWithIndex(uint256,uint256,uint256)")
    LogQuadrupleArg = _encode_to_topic("LogQuadrupleArg(uint256,uint256,uint256,uint256)")
    LogQuadrupleWithIndex = _encode_to_topic(
        "LogQuadrupleWithIndex(uint256,uint256,uint256,uint256)",
    )
    LogBytes = _encode_to_topic("LogBytes(bytes)")
    LogString = _encode_to_topic("LogString(string)")
    LogDynamicArgs = _encode_to_topic("LogDynamicArgs(string,string)")
    LogListArgs = _encode_to_topic("LogListArgs(bytes2[],bytes2[])")
    LogAddressIndexed = _encode_to_topic("LogAddressIndexed(address,address)")
    LogAddressNotIndexed = _encode_to_topic("LogAddressNotIndexed(address,address)")


@pytest.fixture()
def emitter_log_topics():
    return LogTopics


@pytest.fixture()
def some_address(address_conversion_func):
    return address_conversion_func('0x5B2063246F2191f18F2675ceDB8b28102e957458')


def invoke_contract(api_call_desig='call',
                    contract=None,
                    contract_function=None,
                    func_args=[],
                    func_kwargs={},
                    tx_params={}):
    allowable_call_desig = ['call', 'transact', 'estimateGas', 'buildTransaction']
    if api_call_desig not in allowable_call_desig:
        raise ValueError("allowable_invoke_method must be one of: %s" % allowable_call_desig)

    function = contract.functions[contract_function]
    result = getattr(function(*func_args, **func_kwargs), api_call_desig)(tx_params)

    return result


@pytest.fixture
def transact(request):
    return functools.partial(invoke_contract, api_call_desig='transact')


@pytest.fixture
def call(request):
    return functools.partial(invoke_contract, api_call_desig='call')


@pytest.fixture
def estimateGas(request):
    return functools.partial(invoke_contract, api_call_desig='estimateGas')


@pytest.fixture
def buildTransaction(request):
    return functools.partial(invoke_contract, api_call_desig='buildTransaction')
